package modelos;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;

import org.hibernate.annotations.OnDelete;
import org.hibernate.annotations.OnDeleteAction;

@Entity
public class Cartao {

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private int id;
	@Column(unique = true, nullable = false) 
	private String numero;
	@OneToOne
	@OnDelete(action = OnDeleteAction.CASCADE)
	private Cliente cliente;
	private Double limiteTotal;
	@OneToMany
	private List<Fatura> faturas;

	
	
	
	public String getNumero() {
		return numero;
	}

	public void setNumero(String numero) {
		this.numero = numero;
	}

	public Cliente getCliente() {
		return cliente;
	}

	public void setCliente(Cliente cliente) {
		this.cliente = cliente;
	}

	public Double getLimiteTotal() {
		return limiteTotal;
	}

	public void setLimiteTotal(Double limiteTotal) {
		this.limiteTotal = limiteTotal;
	}

	public List<Fatura> getFaturas() {
		return faturas;
	}

	public void setFaturas(List<Fatura> faturas) {
		this.faturas = faturas;
	}

	public Cartao(Cliente cliente, String numero) {
		this.cliente = cliente;
		this.numero = numero;
		this.calculaLimite();
	}

	private void calculaLimite() {
		if (this.cliente != null) {
			this.limiteTotal = this.cliente.getRenda() * 0.70;
		}
	}

	public Fatura buscarFaturaAberta() {
		for (Fatura fatura : this.faturas) {
			if (fatura.isFaturaAberta()) {
				return fatura;
			}
		}
		return null;
	}

	public Double somaValoresFaturas() {
		Double soma = 0.00;
		for (Fatura fatura : this.faturas) {
			soma = fatura.getTotal();
		}
		return soma;
	}

	private boolean adicionarCompraNaFatura(Fatura faturaAberta, Compra compra) {
		faturaAberta.adicionarCompra(compra);

		if (compra.getQuantidadeParc() > 1) {
			int qtdParcelas = compra.getQuantidadeParc();
			Double totalFatura = faturaAberta.getTotal();
			totalFatura += compra.getValorParcela();
			faturaAberta.setTotal(totalFatura);
			faturaAberta.setMinimo(totalFatura * 0.10);
			if (this.faturas.size() < qtdParcelas) {
				this.gerarFaturas(compra, qtdParcelas, totalFatura);
			} else {
				int indexFaturaAberta = this.faturas.indexOf(faturaAberta);
				this.preencherValoresNasFaturasExistentes(compra, qtdParcelas,
						totalFatura, indexFaturaAberta);
			}
		} else {
			Double totalFatura = faturaAberta.getTotal();
			totalFatura += compra.getValorTotal();
			faturaAberta.setTotal(totalFatura);
			faturaAberta.setMinimo(totalFatura * 0.10);
		}
		return true;
	}

	private void gerarFaturas(Compra compra, int qtdParcelas, Double totalFatura) {
		for (int i = 1; i < qtdParcelas; i++) {
			Fatura fat = new Fatura(0.00, 0.00);
			fat.adicionarCompra(compra);
			totalFatura = fat.getTotal();
			totalFatura += compra.getValorParcela();
			fat.setTotal(totalFatura);
			fat.setMinimo(totalFatura * 0.10);
			this.faturas.add(fat);
		}
	}

	private void preencherValoresNasFaturasExistentes(Compra compra,
			int qtdParcelas, Double totalFatura, int indexFaturaAberta) {
		for (int i = 1; i < qtdParcelas; i++) {
			Fatura fatura = this.faturas.get(indexFaturaAberta + i);
			totalFatura = fatura.getTotal();
			totalFatura += compra.getValorParcela();
			fatura.adicionarCompra(compra);
			fatura.setTotal(totalFatura);
			fatura.setMinimo(totalFatura * 0.10);
		}
	}

	public boolean realizarCompra(Compra compra) {
		if (compra != null) {
			Double valorLimite = this.somaValoresFaturas()
					+ compra.getValorTotal();
			if (this.limiteTotal >= valorLimite) {
				if (this.faturas.isEmpty()) {
					Fatura f = new Fatura(0.00, 0.00);
					f.setFaturaAberta(true);
					this.faturas.add(f);
				}
				Fatura faturaAberta = this.buscarFaturaAberta();
				if (faturaAberta != null) {
					return this.adicionarCompraNaFatura(faturaAberta, compra);
				}
			}
		}
		return false;
	}

	public boolean fecharFaturaAberta() {
		Fatura faturaAberta = this.buscarFaturaAberta();
		if (faturaAberta != null) {
			int indexFaturaAberta = this.faturas.indexOf(faturaAberta);
			faturaAberta.setFaturaAberta(false);
			Fatura ultimaFatura = this.faturas.get(this.faturas.size() - 1);
			if (!faturaAberta.equals(ultimaFatura)) {
				Fatura proximaFaturaAberta = this.faturas
						.get(indexFaturaAberta + 1);
				proximaFaturaAberta.setFaturaAberta(true);
			} else {
				Fatura novaFatura = new Fatura(0.00, 0.00);
				novaFatura.setFaturaAberta(true);
				this.faturas.add(novaFatura);
			}
			return true;
		} else {
			return false;
		}
	}

	public boolean pagarFatura(Double valorPago) {
		Fatura faturaAberta = this.buscarFaturaAberta();
		if (faturaAberta == null || valorPago == null) {
			return false;
		} else {
			int indexFaturaAberta = this.faturas.indexOf(faturaAberta);
			if (indexFaturaAberta == 0) {
				return false;
			}
			Fatura faturaFechada = this.faturas.get(indexFaturaAberta - 1);
			if (valorPago < faturaFechada.getMinimo()) {
				return false;
			} else if (valorPago < faturaFechada.getTotal()) {
				Double resto = faturaFechada.getTotal() - valorPago;
				Double juros = (resto) * 0.50;
				Double totalFatura = faturaAberta.getTotal();
				totalFatura += (juros + resto);
				faturaAberta.setTotal(totalFatura);
			}
			faturaFechada.setPago(true);
		}
		return true;
	}

}
